home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / HydraCom / hydracom-source.lha / amiga.c < prev    next >
C/C++ Source or Header  |  1996-10-11  |  52KB  |  2,503 lines

  1. /*
  2. **    :ts=4
  3. **
  4. **    Amiga support module for HYDRA protocol sample implementation.
  5. **
  6. **    Written by    Olaf Barthel
  7. **            Brabeckstrasse 35
  8. **            D-30559 Hannover
  9. **
  10. **            eMail: olsen@sourcery.han.de
  11. **
  12. **    Freely distributable.
  13. */
  14.  
  15.     /* System includes. */
  16.  
  17. #include <intuition/intuitionbase.h>
  18.  
  19. #include <libraries/gadtools.h>
  20. #include <libraries/locale.h>
  21. #include <libraries/asl.h>
  22.  
  23. #include <graphics/gfxbase.h>
  24.  
  25. #include <utility/date.h>
  26.  
  27. #include <devices/conunit.h>
  28. #include <devices/serial.h>
  29. #include <devices/timer.h>
  30.  
  31. #include <hardware/cia.h>
  32.  
  33. #include <dos/dosextens.h>
  34. #include <dos/filehandler.h>
  35. #include <dos/dostags.h>
  36. #include <dos/dosasl.h>
  37.  
  38. #include <exec/memory.h>
  39.  
  40. #include <clib/intuition_protos.h>
  41. #include <clib/gadtools_protos.h>
  42. #include <clib/graphics_protos.h>
  43. #include <clib/utility_protos.h>
  44. #include <clib/locale_protos.h>
  45. #include <clib/timer_protos.h>
  46. #include <clib/exec_protos.h>
  47. #include <clib/dos_protos.h>
  48. #include <clib/asl_protos.h>
  49. #include <clib/macros.h>
  50.  
  51. #include <pragmas/intuition_pragmas.h>
  52. #include <pragmas/gadtools_pragmas.h>
  53. #include <pragmas/graphics_pragmas.h>
  54. #include <pragmas/utility_pragmas.h>
  55. #include <pragmas/locale_pragmas.h>
  56. #include <pragmas/timer_pragmas.h>
  57. #include <pragmas/exec_pragmas.h>
  58. #include <pragmas/dos_pragmas.h>
  59. #include <pragmas/asl_pragmas.h>
  60.  
  61. #include <errno.h>
  62.  
  63. //#define DB(x)    x
  64. #define DB(x) ;
  65.  
  66. void __stdargs kprintf(STRPTR,...);
  67.  
  68. #include "Rendezvous.h"
  69. #include "hydracom.h"
  70.  
  71.     /* Difference between UTC and Amiga time. */
  72.  
  73. #define UTC_OFFSET            252482400
  74.  
  75.     /* Minimum of lines to reserve for local input. */
  76.  
  77. #define MIN_LINES            3
  78.  
  79.     /* Serial buffer size. */
  80.  
  81. #define BUFFER_SIZE            8192
  82.  
  83.     /* Maximum length of a file name for now. */
  84.  
  85. #define MAX_FILENAME_LENGTH    256
  86.  
  87.     /* A handy macro. */
  88.  
  89. #define ClrSignal(s)    SetSignal(0,s)
  90.  
  91.     /* this macro lets us long-align structures on the stack */
  92.  
  93. #define D_S(type,name) char a_##name[sizeof(type)+3]; \
  94.                        type *name = (type *)((LONG)(a_##name+3) & ~3);
  95.  
  96.     /* Signal masks. */
  97.  
  98. #define SIG_SERREAD        (1UL << ReadPort->mp_SigBit)
  99. #define SIG_SERWRITE    (1UL << WritePort->mp_SigBit)
  100. #define SIG_CONREAD        (1UL << ConsoleReadPort->mp_SigBit)
  101. #define SIG_TIMER        (1UL << TimePort->mp_SigBit)
  102. #define SIG_WINDOW        (1UL << WindowPort->mp_SigBit)
  103. #define SIG_HANDSHAKE    SIGF_SINGLE
  104. #define SIG_KILL        SIGBREAKF_CTRL_C
  105.  
  106.     /* A serial buffer structure. */
  107.  
  108. struct SerialBuffer
  109. {
  110.     struct IOExtSer    *SerialRequest;
  111.     UBYTE            *SerialBuffer,
  112.                     *SerialIndex,
  113.                     *SerialTop;
  114.     LONG             SerialSize,
  115.                      SerialFilled;
  116.     BOOL             IsClone,
  117.                      IsBusy;
  118. };
  119.  
  120.     /* Special rendezvous data. */
  121.  
  122. STATIC struct RendezvousData        *RendezvousData;
  123. STATIC struct RendezvousSemaphore    *RendezvousSemaphore;
  124.  
  125.     /* Library bases. */
  126.  
  127. extern struct ExecBase        *SysBase;
  128. extern struct DosLibrary    *DOSBase;
  129.  
  130. struct IntuitionBase        *IntuitionBase;
  131. struct GfxBase                *GfxBase;
  132. struct LocaleBase            *LocaleBase;
  133. struct Library                *GadToolsBase,
  134.                             *UtilityBase,
  135.                             *TimerBase,
  136.                             *AslBase;
  137.  
  138.     /* Timer data. */
  139.  
  140. struct MsgPort        *TimePort;
  141. struct timerequest    *TimeRequest;
  142.  
  143.     /* Serial data. */
  144.  
  145. struct MsgPort        *ReadPort,
  146.                     *WritePort;
  147.  
  148. struct SerialBuffer    *ThisBuffer,
  149.                     *NextBuffer,
  150.                     *ReadBuffer;
  151.  
  152.     /* Console data. */
  153.  
  154. struct MsgPort        *WindowPort;
  155.  
  156. struct Window        *FileWindow,
  157.                     *RemoteWindow,
  158.                     *LocalWindow,
  159.                     *LogWindow;
  160.  
  161. struct MsgPort        *ConsoleWritePort,
  162.                     *ConsoleReadPort;
  163. struct IOStdReq        *ConsoleReadRequest;
  164. UBYTE                 ConsoleChar;
  165. BOOL                 ConsoleReady = FALSE,
  166.                      WindowReady = FALSE;
  167.  
  168. struct IOStdReq        *FileRequest,
  169.                     *RemoteRequest,
  170.                     *LocalRequest,
  171.                     *LogRequest;
  172.  
  173.     /* DOS Data. */
  174.  
  175. struct Process        *ThisProcess;
  176. APTR                 OldPtr;
  177. LONG                 OldPri;
  178.  
  179. struct AnchorPath    *Anchor;
  180. BOOL                 AnchorUsed = FALSE;
  181.  
  182.     /* Screen data. */
  183.  
  184. struct Screen        *PublicScreen,
  185.                     *Screen;
  186.  
  187.     /* Menu data. */
  188.  
  189. APTR                 VisualInfo;
  190. struct Menu            *Menu;
  191.  
  192. struct NewMenu MenuTemplate[] =
  193. {
  194.     { NM_TITLE, "Project",                 0 ,    0,    0,    (APTR)0},
  195.     {  NM_ITEM, "Toggle chat",            "C",    0,    0,    (APTR)Alt_C},
  196.     {  NM_ITEM, NM_BARLABEL,             0 ,    0,    0,    (APTR)0},
  197.     {  NM_ITEM, "Hang up",                "H",    0,    0,    (APTR)Alt_H},
  198.     {  NM_ITEM, "Toggle duplex",        "E",    0,    0,    (APTR)Alt_E},
  199.     {  NM_ITEM, "Toggle 7 bits/8 bits",    "B",    0,    0,    (APTR)Alt_B},
  200.     {  NM_ITEM, NM_BARLABEL,             0 ,    0,    0,    (APTR)0},
  201.     {  NM_ITEM, "Start upload",            "U",    0,    0,    (APTR)PgUp},
  202.     {  NM_ITEM, "Start download",        "D",    0,    0,    (APTR)PgDn},
  203.     {  NM_ITEM, NM_BARLABEL,             0 ,    0,    0,    (APTR)0},
  204.     {  NM_ITEM, "Abort Hydra session",    ".",    0,    0,    (APTR)Esc},
  205.     {  NM_ITEM, NM_BARLABEL,             0 ,    0,    0,    (APTR)0},
  206.     {  NM_ITEM, "Exit HydraCom",        "Q",    0,    0,    (APTR)Alt_X},
  207.     { NM_END }
  208. };
  209.  
  210.     /* Time data. */
  211.  
  212. LONG             GMT_Offset = UTC_OFFSET;
  213.  
  214.     /* Standard file requester. */
  215.  
  216. struct FileRequester *FileRequester;
  217.  
  218.     /* Version ID. */
  219.  
  220. STRPTR VersionTag = "$VER: hydracom 1.0r7 (15.12.95)\r\n";
  221.  
  222.     /* CloseWindowSafely(struct Window *Window):
  223.      *
  224.      *    Close a window sharing its UserPort with other
  225.      *    windows.
  226.      */
  227.  
  228. STATIC VOID
  229. CloseWindowSafely(struct Window *Window)
  230. {
  231.     Forbid();
  232.  
  233.     if(Window->UserPort)
  234.     {
  235.         struct Node *Node,*Next;
  236.  
  237.         for(Node = Window->UserPort->mp_MsgList.lh_Head ; Next = Node->ln_Succ ; Node = Next)
  238.         {
  239.             if(((struct IntuiMessage *)Node)->IDCMPWindow == Window)
  240.             {
  241.                 Remove(Node);
  242.                 ReplyMsg((struct Message *)Node);
  243.             }
  244.         }
  245.  
  246.         Window->UserPort = NULL;
  247.     }
  248.  
  249.     ModifyIDCMP(Window,NULL);
  250.  
  251.     Permit();
  252.  
  253.     CloseWindow(Window);
  254. }
  255.  
  256.     /* UpdateTime(struct timeval *Now):
  257.      *
  258.      *    Get the current time and/or update the current
  259.      *    time offset data.
  260.      */
  261.  
  262. STATIC VOID
  263. UpdateTime(struct timeval *Now)
  264. {
  265.     if(Now)
  266.         Now->tv_secs = Now->tv_micro = 0;
  267.  
  268.     if(TimePort = CreateMsgPort())
  269.     {
  270.         if(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest)))
  271.         {
  272.             if(!OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,NULL))
  273.             {
  274.                 TimerBase = (struct Library *)TimeRequest->tr_node.io_Device;
  275.  
  276.                 if(LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38))
  277.                 {
  278.                     struct Locale *Locale = OpenLocale(NULL);
  279.  
  280.                     GMT_Offset = 60 * Locale->loc_GMTOffset + UTC_OFFSET;
  281.                     CloseLocale(Locale);
  282.  
  283.                     CloseLibrary(LocaleBase);
  284.                     LocaleBase = NULL;
  285.                 }
  286.  
  287.                 if(Now)
  288.                     GetSysTime(Now);
  289.  
  290.                 TimerBase = NULL;
  291.                 CloseDevice(TimeRequest);
  292.             }
  293.  
  294.             DeleteIORequest(TimeRequest);
  295.             TimeRequest = NULL;
  296.         }
  297.  
  298.         DeleteMsgPort(TimePort);
  299.         TimePort = NULL;
  300.     }
  301. }
  302.  
  303. STATIC VOID
  304. AddString(STRPTR Buffer,LONG MaxLen,STRPTR NewString)
  305. {
  306.     LONG i,Len,BufferLen;
  307.     BOOL HasSpace;
  308.  
  309.     Len            = strlen(NewString);
  310.     BufferLen    = strlen(Buffer);
  311.     HasSpace    = FALSE;
  312.  
  313.     for(i = 0 ; i < Len ; i++)
  314.     {
  315.         if(NewString[i] == ' ')
  316.         {
  317.             HasSpace = TRUE;
  318.             Len += 2;
  319.             break;
  320.         }
  321.     }
  322.  
  323.     Len++;
  324.  
  325.     if(BufferLen + Len < MaxLen)
  326.     {
  327.         if(HasSpace)
  328.             sprintf(&Buffer[BufferLen],"\"%s\" ",NewString);
  329.         else
  330.             sprintf(&Buffer[BufferLen],"%s ",NewString);
  331.     }
  332. }
  333.  
  334.     /* GetFiles(char *Buffer,int MaxLen):
  335.      *
  336.      *    Get a list of file names.
  337.      */
  338.  
  339. char *
  340. GetFiles(char *Buffer,int MaxLen)
  341. {
  342.     if(AslRequestTags(FileRequester,
  343.         ASLFR_Window,        LocalWindow,
  344.         ASLFR_SleepWindow,    TRUE,
  345.     TAG_DONE))
  346.     {
  347.         if(FileRequester->fr_NumArgs > 0)
  348.         {
  349.             UBYTE    LocalBuffer[MAX_FILENAME_LENGTH];
  350.             LONG    Len,Count,i;
  351.  
  352.             for(i = Count = 0 ; i < FileRequester->fr_NumArgs ; i++)
  353.             {
  354.                 if(FileRequester->fr_ArgList[i].wa_Lock)
  355.                 {
  356.                     if(!NameFromLock(FileRequester->fr_ArgList[i].wa_Lock,LocalBuffer,sizeof(LocalBuffer)))
  357.                     {
  358.                         Count = -1;
  359.                         break;
  360.                     }
  361.                 }
  362.                 else
  363.                 {
  364.                     Len = strlen(FileRequester->fr_Drawer);
  365.  
  366.                     if(Len >= sizeof(LocalBuffer))
  367.                     {
  368.                         Count = -1;
  369.                         break;
  370.                     }
  371.                     else
  372.                         strcpy(LocalBuffer,FileRequester->fr_Drawer);
  373.                 }
  374.  
  375.                 if(AddPart(LocalBuffer,FileRequester->fr_ArgList[i].wa_Name,sizeof(LocalBuffer)))
  376.                 {
  377.                     LONG j;
  378.  
  379.                     Len = strlen(LocalBuffer) + 1;
  380.  
  381.                     for(j = 0 ; j < Len ; j++)
  382.                     {
  383.                         if(j == ' ')
  384.                         {
  385.                             Len += 2;
  386.                             break;
  387.                         }
  388.                     }
  389.  
  390.                     if(Len < sizeof(LocalBuffer))
  391.                     {
  392.                         if(Count + Len < MaxLen)
  393.                             Count += Len;
  394.                         else
  395.                         {
  396.                             Count = -1;
  397.                             break;
  398.                         }
  399.                     }
  400.                 }
  401.             }
  402.  
  403.             if(Count > 0)
  404.             {
  405.                 Buffer[0] = 0;
  406.  
  407.                 for(i = 0 ; i < FileRequester->fr_NumArgs ; i++)
  408.                 {
  409.                     if(FileRequester->fr_ArgList[i].wa_Lock)
  410.                     {
  411.                         if(!NameFromLock(FileRequester->fr_ArgList[i].wa_Lock,LocalBuffer,sizeof(LocalBuffer)))
  412.                             break;
  413.                     }
  414.                     else
  415.                     {
  416.                         Len = strlen(FileRequester->fr_Drawer);
  417.  
  418.                         if(Len >= sizeof(LocalBuffer))
  419.                             break;
  420.                         else
  421.                             strcpy(LocalBuffer,FileRequester->fr_Drawer);
  422.                     }
  423.  
  424.                     if(AddPart(LocalBuffer,FileRequester->fr_ArgList[i].wa_Name,sizeof(LocalBuffer)))
  425.                         AddString(Buffer,MaxLen,LocalBuffer);
  426.                 }
  427.  
  428.                 return(Buffer);
  429.             }
  430.         }
  431.         else
  432.         {
  433.             if(FileRequester->fr_File[0])
  434.             {
  435.                 LONG Len;
  436.  
  437.                 Len = strlen(FileRequester->fr_Drawer) + strlen(FileRequester->fr_File) + 2 + 2;
  438.  
  439.                 if(Len <= MaxLen)
  440.                 {
  441.                     strcpy(Buffer,FileRequester->fr_Drawer);
  442.                     AddPart(Buffer,FileRequester->fr_File,MaxLen);
  443.  
  444.                     return(Buffer);
  445.                 }
  446.             }
  447.         }
  448.     }
  449.  
  450.     return(NULL);
  451. }
  452.  
  453.     /* OpenConsole():
  454.      *
  455.      *    Open a console window.
  456.      */
  457.  
  458. STATIC BOOL
  459. OpenConsole(struct Screen *Screen,LONG Top,LONG Height,STRPTR Title,BOOL Resize,struct Window **WindowPtr,struct IOStdReq **ConsolePtr)
  460. {
  461.     struct Window *Window;
  462.  
  463.     if(Window = OpenWindowTags(NULL,
  464.         WA_Left,            0,
  465.         WA_Top,                Top,
  466.         WA_Width,            Screen->Width,
  467.         WA_Height,            Height,
  468.         WA_Title,            Title,
  469.         WA_SimpleRefresh,    TRUE,
  470.         WA_DepthGadget,        TRUE,
  471.         WA_DragBar,            TRUE,
  472.         WA_SizeGadget,        Resize,
  473.         WA_SizeBRight,        TRUE,
  474.         WA_CustomScreen,    Screen,
  475.         WA_NewLookMenus,    TRUE,
  476.     TAG_DONE))
  477.     {
  478.         Window->UserPort = WindowPort;
  479.  
  480.         SetMenuStrip(Window,Menu);
  481.  
  482.         if(ModifyIDCMP(Window,IDCMP_MENUPICK))
  483.         {
  484.             struct IOStdReq *ConsoleRequest;
  485.  
  486.             if(Window->RPort->Font->tf_Flags & FPF_PROPORTIONAL)
  487.                 SetFont(Window->RPort,GfxBase->DefaultFont);
  488.  
  489.             if(ConsoleRequest = (struct IOStdReq *)CreateIORequest(ConsoleWritePort,sizeof(struct IOStdReq)))
  490.             {
  491.                 ConsoleRequest->io_Data = Window;
  492.  
  493.                 if(!OpenDevice("console.device",CONU_CHARMAP,ConsoleRequest,CONFLAG_DEFAULT))
  494.                 {
  495.                     WindowLimits(Window,Window->BorderLeft + 10 * Window->RPort->Font->tf_XSize * 10 + Window->BorderRight,Window->BorderTop + 2 * Window->RPort->Font->tf_YSize + Window->BorderBottom,Screen->Width,Screen->Height);
  496.  
  497.                         /* Turn off the cursor. */
  498.  
  499.                     ConPrintf(ConsoleRequest,"\033[0 p");
  500.  
  501.                     *WindowPtr    = Window;
  502.                     *ConsolePtr    = ConsoleRequest;
  503.  
  504.                     return(TRUE);
  505.                 }
  506.  
  507.                 DeleteIORequest(ConsoleRequest);
  508.             }
  509.         }
  510.  
  511.         ClearMenuStrip(Window);
  512.  
  513.         CloseWindowSafely(Window);
  514.     }
  515.  
  516.     return(FALSE);
  517. }
  518.  
  519.     /* CloseConsole():
  520.      *
  521.      *    Close a console window.
  522.      */
  523.  
  524. STATIC VOID
  525. CloseConsole(struct Window **WindowPtr,struct IOStdReq **ConsolePtr)
  526. {
  527.     if(*ConsolePtr)
  528.     {
  529.         CloseDevice(*ConsolePtr);
  530.  
  531.         DeleteIORequest(*ConsolePtr);
  532.  
  533.         *ConsolePtr = NULL;
  534.     }
  535.  
  536.     if(*WindowPtr)
  537.     {
  538.         ClearMenuStrip(*WindowPtr);
  539.  
  540.         CloseWindowSafely(*WindowPtr);
  541.  
  542.         *WindowPtr = NULL;
  543.     }
  544. }
  545.  
  546.     /* CloneSerialBuffer():
  547.      *
  548.      *    Clone a SerialBuffer structure.
  549.      */
  550.  
  551. STATIC struct SerialBuffer *
  552. CloneSerialBuffer(struct SerialBuffer *Source,struct MsgPort *MsgPort)
  553. {
  554.     struct SerialBuffer *Buffer;
  555.  
  556.     if(Buffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + Source->SerialSize,MEMF_ANY | MEMF_PUBLIC))
  557.     {
  558.         Buffer->SerialBuffer    = Buffer->SerialIndex = (UBYTE *)(Buffer + 1);
  559.         Buffer->SerialFilled    = 0;
  560.         Buffer->SerialTop        = Buffer->SerialBuffer + Source->SerialSize;
  561.         Buffer->SerialSize        = Source->SerialSize;
  562.         Buffer->IsClone            = TRUE;
  563.         Buffer->IsBusy            = FALSE;
  564.  
  565.         if(Buffer->SerialRequest = (struct IOExtSer *)AllocVec(sizeof(struct IOExtSer),MEMF_ANY | MEMF_PUBLIC))
  566.         {
  567.             CopyMem(Source->SerialRequest,Buffer->SerialRequest,sizeof(struct IOExtSer));
  568.  
  569.             Buffer->SerialRequest->IOSer.io_Message.mn_ReplyPort = MsgPort;
  570.  
  571.             return(Buffer);
  572.         }
  573.         else
  574.             cprint("Could not create serial request\n");
  575.  
  576.         FreeVec(Buffer);
  577.     }
  578.     else
  579.         cprint("Could not create serial buffer\n");
  580.  
  581.     return(NULL);
  582. }
  583.  
  584.     /* DeleteSerialBuffer():
  585.      *
  586.      *    Delete a SerialBuffer structure.
  587.      */
  588.  
  589. STATIC VOID
  590. DeleteSerialBuffer(struct SerialBuffer *Buffer)
  591. {
  592.     if(Buffer)
  593.     {
  594.         if(Buffer->IsBusy)
  595.         {
  596.             if(!CheckIO(Buffer->SerialRequest))
  597.                 AbortIO(Buffer->SerialRequest);
  598.  
  599.             WaitIO(Buffer->SerialRequest);
  600.         }
  601.  
  602.         if(Buffer->IsClone)
  603.             FreeVec(Buffer->SerialRequest);
  604.         else
  605.         {
  606.             CloseDevice(Buffer->SerialRequest);
  607.  
  608.             DeleteIORequest(Buffer->SerialRequest);
  609.         }
  610.  
  611.         FreeVec(Buffer);
  612.     }
  613. }
  614.  
  615.     /* CreateSerialBuffer():
  616.      *
  617.      *    Create a serial buffer structure.
  618.      */
  619.  
  620. STATIC struct SerialBuffer *
  621. CreateSerialBuffer(STRPTR Device,LONG Unit,LONG Size,struct MsgPort *MsgPort)
  622. {
  623.     struct SerialBuffer *Buffer;
  624.  
  625.     if(Buffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + Size,MEMF_ANY | MEMF_PUBLIC))
  626.     {
  627.         Buffer->SerialBuffer    = Buffer->SerialIndex = (UBYTE *)(Buffer + 1);
  628.         Buffer->SerialFilled    = 0;
  629.         Buffer->SerialTop        = Buffer->SerialBuffer + Size;
  630.         Buffer->SerialSize        = Size;
  631.         Buffer->IsClone            = FALSE;
  632.         Buffer->IsBusy            = FALSE;
  633.  
  634.         if(Buffer->SerialRequest = (struct IOExtSer *)CreateIORequest(MsgPort,sizeof(struct IOExtSer)))
  635.         {
  636.             Buffer->SerialRequest->io_SerFlags = SERF_SHARED|SERF_7WIRE;
  637.  
  638.             if(!OpenDevice(Device,Unit,Buffer->SerialRequest,NULL))
  639.                 return(Buffer);
  640.             else
  641.             {
  642.                 cprint("Could not open \"%s\", unit %d\n",Device,Unit);
  643.  
  644.                 DeleteIORequest(Buffer->SerialRequest);
  645.             }
  646.         }
  647.         else
  648.             cprint("Could not create serial request\n");
  649.  
  650.         FreeVec(Buffer);
  651.     }
  652.     else
  653.         cprint("Could not create serial buffer\n");
  654.  
  655.     return(NULL);
  656. }
  657.  
  658.     /* OpenAll():
  659.      *
  660.      *    Allocate all the resources required.
  661.      */
  662.  
  663. STATIC BOOL
  664. OpenAll(STRPTR Device,LONG Unit)
  665. {
  666.     LONG Top,Lines,BorderSize,FontSize,ExtraLines,RemainingLines,TotalHeight;
  667.     UWORD Pens = (UWORD)~0;
  668.  
  669.     ThisProcess = (struct Process *)FindTask(NULL);
  670.  
  671.     if(pri != 1000)
  672.     {
  673.         if(pri < -128)
  674.             pri = 128;
  675.         else
  676.         {
  677.             if(pri > 127)
  678.                 pri = 127;
  679.         }
  680.  
  681.         OldPri = SetTaskPri(ThisProcess,pri);
  682.     }
  683.  
  684.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
  685.     {
  686.         cprint("Could not open intuition.library v37\n");
  687.  
  688.         return(FALSE);
  689.     }
  690.  
  691.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
  692.     {
  693.         cprint("Could not open graphics.library v37\n");
  694.  
  695.         return(FALSE);
  696.     }
  697.  
  698.     if(!(GadToolsBase = OpenLibrary("gadtools.library",37)))
  699.     {
  700.         cprint("Could not open gadtools.library v37\n");
  701.  
  702.         return(FALSE);
  703.     }
  704.  
  705.     if(!(UtilityBase = OpenLibrary("utility.library",37)))
  706.     {
  707.         cprint("Could not open utility.library v37\n");
  708.  
  709.         return(FALSE);
  710.     }
  711.  
  712.     if(!(AslBase = OpenLibrary("asl.library",37)))
  713.     {
  714.         cprint("Could not open asl.library v37\n");
  715.  
  716.         return(FALSE);
  717.     }
  718.  
  719.     if(!(FileRequester = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  720.         ASLFR_TitleText,        "Select file(s) to upload",
  721.         ASLFR_InitialPattern,    "#?",
  722.         ASLFR_Flags1,            FRF_PRIVATEIDCMP | FRF_DOMULTISELECT | FRF_DOPATTERNS,
  723.     TAG_DONE)))
  724.     {
  725.         cprint("Could not allocate file requester.\n");
  726.  
  727.         return(FALSE);
  728.     }
  729.  
  730.     if(LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38))
  731.     {
  732.         struct Locale *Locale;
  733.  
  734.         if(Locale = OpenLocale(NULL))
  735.         {
  736.             GMT_Offset = 60 * Locale->loc_GMTOffset + UTC_OFFSET;
  737.  
  738.             CloseLocale(Locale);
  739.         }
  740.  
  741.         CloseLibrary(LocaleBase);
  742.     }
  743.  
  744.     if(!(TimePort = CreateMsgPort()))
  745.     {
  746.         cprint("Could not create timer port\n");
  747.  
  748.         return(FALSE);
  749.     }
  750.  
  751.     if(!(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest))))
  752.     {
  753.         cprint("Could not create timer request\n");
  754.  
  755.         return(FALSE);
  756.     }
  757.  
  758.     if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,NULL))
  759.     {
  760.         cprint("Could not open timer\n");
  761.  
  762.         return(FALSE);
  763.     }
  764.  
  765.     TimerBase = (struct Library *)TimeRequest->tr_node.io_Device;
  766.  
  767.     if(!(Anchor = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath) + 512,MEMF_ANY | MEMF_CLEAR)))
  768.     {
  769.         cprint("Could not allocate pattern matching buffe\n");
  770.  
  771.         return(FALSE);
  772.     }
  773.  
  774.     Anchor->ap_Strlen = 512;
  775.  
  776.     if(!(ReadPort = CreateMsgPort()))
  777.     {
  778.         cprint("Could not create serial read port\n");
  779.  
  780.         return(FALSE);
  781.     }
  782.  
  783.     if(!(WritePort = CreateMsgPort()))
  784.     {
  785.         cprint("Could not create serial write port\n");
  786.  
  787.         return(FALSE);
  788.     }
  789.  
  790.     Forbid();
  791.  
  792.     if(RendezvousSemaphore = (struct RendezvousSemaphore *)FindSemaphore(Device))
  793.     {
  794.         ObtainSemaphore(RendezvousSemaphore);
  795.  
  796.         if(!(RendezvousData = (*RendezvousSemaphore->rs_Login)(ReadPort,WritePort,NULL)))
  797.         {
  798.             Permit();
  799.  
  800.             ReleaseSemaphore(RendezvousSemaphore);
  801.  
  802.             RendezvousSemaphore = NULL;
  803.  
  804.             cprint("Could not link to `term' port \"%s\"\n",Device);
  805.  
  806.             return(FALSE);
  807.         }
  808.     }
  809.  
  810.     Permit();
  811.  
  812.     if(!(ConsoleReadPort = CreateMsgPort()))
  813.     {
  814.         cprint("Could not create console read port\n");
  815.  
  816.         return(FALSE);
  817.     }
  818.  
  819.     if(!(ConsoleWritePort = CreateMsgPort()))
  820.     {
  821.         cprint("Could not create console write port\n");
  822.  
  823.         return(FALSE);
  824.     }
  825.  
  826.     if(!(ConsoleReadRequest = (struct IOStdReq *)AllocVec(sizeof(struct IOStdReq),MEMF_ANY | MEMF_PUBLIC | MEMF_CLEAR)))
  827.     {
  828.         cprint("Could not create console read request\n");
  829.  
  830.         return(FALSE);
  831.     }
  832.  
  833.     if(!RendezvousData)
  834.     {
  835.         if(!(ReadBuffer = CreateSerialBuffer(Device,Unit,BUFFER_SIZE,ReadPort)))
  836.             return(FALSE);
  837.     }
  838.     else
  839.     {
  840.         if(ReadBuffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + BUFFER_SIZE,MEMF_ANY | MEMF_PUBLIC))
  841.         {
  842.             ReadBuffer->SerialBuffer    = ReadBuffer->SerialIndex = (UBYTE *)(ReadBuffer + 1);
  843.             ReadBuffer->SerialFilled    = 0;
  844.             ReadBuffer->SerialTop        = ReadBuffer->SerialBuffer + BUFFER_SIZE;
  845.             ReadBuffer->SerialSize        = BUFFER_SIZE;
  846.             ReadBuffer->IsClone            = TRUE;
  847.             ReadBuffer->IsBusy            = FALSE;
  848.             ReadBuffer->SerialRequest    = &RendezvousData->rd_ReadRequest;
  849.  
  850.                 /* Ralph Seichter suggested reusing the data
  851.                  * stored in the rendezvous data.
  852.                  */
  853.  
  854.             com_speed = ReadBuffer->SerialRequest->io_Baud;
  855.  
  856.             if(cur_speed > com_speed)
  857.                 cur_speed = com_speed;
  858.  
  859.             if(ReadBuffer->SerialRequest->io_ReadLen == 7 && ReadBuffer->SerialRequest->io_WriteLen == 7 && (ReadBuffer->SerialRequest->io_SerFlags & (SERF_PARTY_ON|SERF_PARTY_ODD)) == SERF_PARTY_ON && !(ReadBuffer->SerialRequest->io_SerFlags & (SEXTF_MSPON|SEXTF_MARK)))
  860.             {
  861.                 parity = true;
  862.                 hydra_options |= HOPT_HIGHBIT;
  863.             }
  864.             else
  865.                 parity = false;
  866.         }
  867.         else
  868.         {
  869.             cprint("Could not create serial ReadBuffer\n");
  870.  
  871.             return(FALSE);
  872.         }
  873.     }
  874.  
  875.     if(!(ThisBuffer = CloneSerialBuffer(ReadBuffer,WritePort)))
  876.         return(FALSE);
  877.  
  878.     if(!(NextBuffer = CloneSerialBuffer(ReadBuffer,WritePort)))
  879.         return(FALSE);
  880.  
  881.     if(!(PublicScreen = LockPubScreen(NULL)))
  882.     {
  883.         cprint("Could not find default public screen\n");
  884.  
  885.         return(FALSE);
  886.     }
  887.  
  888.     if(RendezvousData)
  889.     {
  890.         if(!(Screen = RendezvousData->rd_Screen))
  891.             Screen = PublicScreen;
  892.     }
  893.     else
  894.     {
  895.         if(!(Screen = OpenScreenTags(NULL,
  896.             SA_DisplayID,    GetVPModeID(&PublicScreen->ViewPort),
  897.             SA_Overscan,    OSCAN_TEXT,
  898.             SA_Depth,        2,
  899.             SA_Title,        PRGNAME " " VERSION " " HC_OS " Amiga rev 8, ported by Olaf `Olsen' Barthel",
  900.             SA_Behind,        TRUE,
  901.             SA_SysFont,        1,
  902.             SA_Pens,        &Pens,
  903.             SA_Interleaved,    TRUE,
  904.         TAG_DONE)))
  905.         {
  906.             cprint("Could not open screen\n");
  907.  
  908.             return(FALSE);
  909.         }
  910.     }
  911.  
  912.     if(!(VisualInfo = GetVisualInfo(Screen,TAG_DONE)))
  913.     {
  914.         cprint("Could not obtain screen visual info\n");
  915.  
  916.         return(FALSE);
  917.     }
  918.  
  919.     if(!(Menu = CreateMenus(MenuTemplate,TAG_DONE)))
  920.     {
  921.         cprint("Could not create menus\n");
  922.  
  923.         return(FALSE);
  924.     }
  925.  
  926.     if(!LayoutMenus(Menu,VisualInfo,
  927.         GTMN_TextAttr,        Screen->Font,
  928.         GTMN_NewLookMenus,    TRUE,
  929.     TAG_DONE))
  930.     {
  931.         cprint("Could not layout menus\n");
  932.  
  933.         return(FALSE);
  934.     }
  935.  
  936.     Top                = Screen->BarHeight + 1;
  937.     BorderSize        = Screen->WBorTop + Screen->Font->ta_YSize + 1 + Screen->WBorBottom;
  938.     FontSize        = GfxBase->DefaultFont->tf_YSize;
  939.     TotalHeight        = Screen->Height - Top;
  940.     Lines            = (TotalHeight - 3 - 4 * BorderSize) / FontSize;
  941.     ExtraLines        = Lines > MIN_LINES ? (Lines - MIN_LINES) / 3 : 0;
  942.     RemainingLines    = Lines > MIN_LINES + ExtraLines * 3 ? Lines - (MIN_LINES + ExtraLines * 3) : 0;
  943.  
  944.     if(Lines < MIN_LINES)
  945.     {
  946.         cprint("Screen size too small (need at least %d text lines, can get only %d)\n",MIN_LINES,Lines);
  947.  
  948.         return(FALSE);
  949.     }
  950.  
  951.     if(!(WindowPort = CreateMsgPort()))
  952.     {
  953.         cprint("Could not create window port\n");
  954.  
  955.         return(FALSE);
  956.     }
  957.  
  958.     if(!OpenConsole(Screen,Top,BorderSize + (6 + ExtraLines) * FontSize,"Log",TRUE,&LogWindow,&LogRequest))
  959.     {
  960.         cprint("Could not open console window #1\n");
  961.  
  962.         return(FALSE);
  963.     }
  964.  
  965.     TotalHeight    -= LogWindow->Height + 1;
  966.     Top            += LogWindow->Height + 1;
  967.  
  968.     if(!OpenConsole(Screen,Top,BorderSize + 2 * FontSize,"File",FALSE,&FileWindow,&FileRequest))
  969.     {
  970.         cprint("Could not open console window #2\n");
  971.  
  972.         return(FALSE);
  973.     }
  974.  
  975.     ConPrintf(FileRequest,"\033[?7l");
  976.  
  977.     TotalHeight    -= FileWindow->Height + 1;
  978.     Top            += FileWindow->Height + 1;
  979.  
  980.     if(!OpenConsole(Screen,Top,BorderSize + (8 + RemainingLines) * FontSize,"Remote",TRUE,&RemoteWindow,&RemoteRequest))
  981.     {
  982.         cprint("Could not open console window #3\n");
  983.  
  984.         return(FALSE);
  985.     }
  986.  
  987.     TotalHeight    -= RemoteWindow->Height + 1;
  988.     Top            += RemoteWindow->Height + 1;
  989.  
  990.     if(!OpenConsole(Screen,Top,TotalHeight,"Local (Press [Amiga+C] to start/end chat mode, [Esc] to abort Hydra session)",TRUE,&LocalWindow,&LocalRequest))
  991.     {
  992.         cprint("Could not open console window #4\n");
  993.  
  994.         return(FALSE);
  995.     }
  996.  
  997.     CopyMem(LocalRequest,ConsoleReadRequest,sizeof(struct IOStdReq));
  998.  
  999.     ConsoleReadRequest->io_Message.mn_ReplyPort = ConsoleReadPort;
  1000.  
  1001.         /* Turn the cursors back on. */
  1002.  
  1003.     ConPrintf(LocalRequest,"\33[ p");
  1004.     ConPrintf(RemoteRequest,"\33[ p");
  1005.  
  1006.     ConsoleReadRequest->io_Command    = CMD_READ;
  1007.     ConsoleReadRequest->io_Data        = &ConsoleChar;
  1008.     ConsoleReadRequest->io_Length    = 1;
  1009.  
  1010.     ClrSignal(SIG_CONREAD);
  1011.     SendIO(ConsoleReadRequest);
  1012.  
  1013.     OldPtr = ThisProcess->pr_WindowPtr;
  1014.  
  1015.     ThisProcess->pr_WindowPtr = (APTR)LocalWindow;
  1016.  
  1017.     if(!quiet)
  1018.     {
  1019.         ScreenToFront(Screen);
  1020.  
  1021.         ActivateWindow(LocalWindow);
  1022.     }
  1023.  
  1024.     UnlockPubScreen(NULL,PublicScreen);
  1025.  
  1026.     PublicScreen = NULL;
  1027.  
  1028.     if(!RendezvousData)
  1029.         com_flow(flowflags);
  1030.  
  1031.     return(TRUE);
  1032. }
  1033.  
  1034.     /* CloseAll():
  1035.      *
  1036.      *    Close all the resources.
  1037.      */
  1038.  
  1039. STATIC VOID
  1040. CloseAll(VOID)
  1041. {
  1042.     if(FileRequester)
  1043.         FreeAslRequest(FileRequester);
  1044.  
  1045.     if(LocalWindow)
  1046.         ClearMenuStrip(LocalWindow);
  1047.  
  1048.     if(Menu)
  1049.         FreeMenus(Menu);
  1050.  
  1051.     if(VisualInfo)
  1052.         FreeVisualInfo(VisualInfo);
  1053.  
  1054.     if(AnchorUsed)
  1055.         MatchEnd(Anchor);
  1056.  
  1057.     if(Anchor)
  1058.         FreeVec(Anchor);
  1059.  
  1060.     if(ThisProcess)
  1061.         ThisProcess->pr_WindowPtr = OldPtr;
  1062.  
  1063.     if(ConsoleReadRequest)
  1064.     {
  1065.         if(ConsoleReadRequest->io_Device)
  1066.         {
  1067.             if(!CheckIO(ConsoleReadRequest))
  1068.                 AbortIO(ConsoleReadRequest);
  1069.  
  1070.             WaitIO(ConsoleReadRequest);
  1071.         }
  1072.  
  1073.         FreeVec(ConsoleReadRequest);
  1074.     }
  1075.  
  1076.     CloseConsole(&LocalWindow,&LocalRequest);
  1077.     CloseConsole(&RemoteWindow,&RemoteRequest);
  1078.     CloseConsole(&FileWindow,&FileRequest);
  1079.     CloseConsole(&LogWindow,&LogRequest);
  1080.  
  1081.     if(WindowPort)
  1082.         DeleteMsgPort(WindowPort);
  1083.  
  1084.     if(!RendezvousData && Screen)
  1085.         CloseScreen(Screen);
  1086.  
  1087.     if(PublicScreen)
  1088.         UnlockPubScreen(NULL,PublicScreen);
  1089.  
  1090.     DeleteSerialBuffer(NextBuffer);
  1091.     DeleteSerialBuffer(ThisBuffer);
  1092.  
  1093.     if(RendezvousData)
  1094.     {
  1095.         if(ReadBuffer->IsBusy)
  1096.         {
  1097.             if(!CheckIO(ReadBuffer->SerialRequest))
  1098.                 AbortIO(ReadBuffer->SerialRequest);
  1099.  
  1100.             WaitIO(ReadBuffer->SerialRequest);
  1101.         }
  1102.  
  1103.         FreeVec(ReadBuffer);
  1104.     }
  1105.     else
  1106.         DeleteSerialBuffer(ReadBuffer);
  1107.  
  1108.     if(ConsoleWritePort)
  1109.         DeleteMsgPort(ConsoleWritePort);
  1110.  
  1111.     if(ConsoleReadPort)
  1112.         DeleteMsgPort(ConsoleReadPort);
  1113.  
  1114.     if(WritePort)
  1115.         DeleteMsgPort(WritePort);
  1116.  
  1117.     if(ReadPort)
  1118.         DeleteMsgPort(ReadPort);
  1119.  
  1120.     if(TimeRequest)
  1121.     {
  1122.         if(TimeRequest->tr_node.io_Device)
  1123.             CloseDevice(TimeRequest);
  1124.  
  1125.         DeleteIORequest(TimeRequest);
  1126.     }
  1127.  
  1128.     if(TimePort)
  1129.         DeleteMsgPort(TimePort);
  1130.  
  1131.     if(UtilityBase)
  1132.         CloseLibrary(UtilityBase);
  1133.  
  1134.     if(AslBase)
  1135.         CloseLibrary(AslBase);
  1136.  
  1137.     if(GadToolsBase)
  1138.         CloseLibrary(GadToolsBase);
  1139.  
  1140.     if(GfxBase)
  1141.         CloseLibrary(GfxBase);
  1142.  
  1143.     if(IntuitionBase)
  1144.         CloseLibrary(IntuitionBase);
  1145.  
  1146.     if(RendezvousData)
  1147.     {
  1148.         (*RendezvousSemaphore->rs_Logoff)(RendezvousData);
  1149.  
  1150.         RendezvousData = NULL;
  1151.     }
  1152.  
  1153.     if(RendezvousSemaphore)
  1154.     {
  1155.         ReleaseSemaphore(RendezvousSemaphore);
  1156.  
  1157.         RendezvousSemaphore = NULL;
  1158.     }
  1159.  
  1160.     if(pri != 1000)
  1161.         OldPri = SetTaskPri(ThisProcess,OldPri);
  1162. }
  1163.  
  1164.     /* ConPutc():
  1165.      *
  1166.      *    Output a single character.
  1167.      */
  1168.  
  1169. VOID __stdargs
  1170. ConPutc(struct IOStdReq *Request,UBYTE Char)
  1171. {
  1172.     Request->io_Command    = CMD_WRITE;
  1173.     Request->io_Data    = &Char;
  1174.     Request->io_Length    = 1;
  1175.  
  1176.     DoIO(Request);
  1177. }
  1178.  
  1179.     /* ConPuts():
  1180.      *
  1181.      *    Output a string.
  1182.      */
  1183.  
  1184. VOID
  1185. ConPuts(struct IOStdReq *Request,STRPTR String)
  1186. {
  1187.     Request->io_Command    = CMD_WRITE;
  1188.     Request->io_Data    = String;
  1189.     Request->io_Length    = strlen(String);
  1190.  
  1191.     DoIO(Request);
  1192. }
  1193.  
  1194.     /* ConPrintf():
  1195.      *
  1196.      *    Formatted console output.
  1197.      */
  1198.  
  1199. VOID __stdargs
  1200. ConPrintf(struct IOStdReq *Request,STRPTR Format,...)
  1201. {
  1202.     STATIC UBYTE Buffer[512];
  1203.  
  1204.     va_list    VarArgs;
  1205.     LONG    Len;
  1206.  
  1207.     va_start(VarArgs,Format);
  1208.     vsprintf(Buffer,Format,VarArgs);
  1209.     va_end(VarArgs);
  1210.  
  1211.     Len = strlen(Buffer);
  1212.  
  1213.     if(Buffer[0] != '\033' && Request == FileRequest)
  1214.     {
  1215.         struct ConUnit *Unit = (struct ConUnit *)Request->io_Unit;
  1216.  
  1217.         if(Unit->cu_XCCP + Len > Unit->cu_XMax)
  1218.         {
  1219.             if((Len = Unit->cu_XMax - Unit->cu_XCCP) < 1)
  1220.                 return;
  1221.         }
  1222.     }
  1223.  
  1224.     Request->io_Command    = CMD_WRITE;
  1225.     Request->io_Data    = Buffer;
  1226.     Request->io_Length    = Len;
  1227.  
  1228.     DoIO(Request);
  1229. }
  1230.  
  1231.     /* ConMove():
  1232.      *
  1233.      *    Move the cursor to a new position.
  1234.      */
  1235.  
  1236. VOID
  1237. ConMove(struct IOStdReq *Request,LONG x,LONG y)
  1238. {
  1239.     ConPrintf(Request,"\33[%ld;%ldH",y,x);
  1240. }
  1241.  
  1242.     /* ConClear():
  1243.      *
  1244.      *    Clear the console window.
  1245.      */
  1246.  
  1247. VOID
  1248. ConClear(struct IOStdReq *Request)
  1249. {
  1250.     struct ConUnit *ConUnit = (struct ConUnit *)Request->io_Device;
  1251.     LONG x,y;
  1252.  
  1253.     x = ConUnit->cu_XCCP;
  1254.     y = ConUnit->cu_YCCP;
  1255.  
  1256.     ConPrintf(Request,"\033[2J\33[%ld;%ldH",y,x);
  1257. }
  1258.  
  1259.     /* ConGetKey():
  1260.      *
  1261.      *    Read a character from a console window.
  1262.      */
  1263.  
  1264. int
  1265. ConGetKey()
  1266. {
  1267.     if(ConsoleReady)
  1268.     {
  1269.         int Result = ConsoleChar;
  1270.  
  1271.         ConsoleReady = FALSE;
  1272.  
  1273.         ConsoleReadRequest->io_Command    = CMD_READ;
  1274.         ConsoleReadRequest->io_Data        = &ConsoleChar;
  1275.         ConsoleReadRequest->io_Length    = 1;
  1276.  
  1277.         ClrSignal(SIG_CONREAD);
  1278.         SendIO(ConsoleReadRequest);
  1279.  
  1280.         return(Result);
  1281.     }
  1282.     else
  1283.     {
  1284.         int Result = 0;
  1285.  
  1286.         if(WindowReady)
  1287.         {
  1288.             struct IntuiMessage *IntuiMessage;
  1289.             ULONG MsgClass;
  1290.             UWORD MsgCode;
  1291.  
  1292.             while(IntuiMessage = (struct IntuiMessage *)GetMsg(LocalWindow->UserPort))
  1293.             {
  1294.                 MsgClass    = IntuiMessage->Class;
  1295.                 MsgCode        = IntuiMessage->Code;
  1296.  
  1297.                 ReplyMsg(IntuiMessage);
  1298.  
  1299.                 if(MsgClass == IDCMP_MENUPICK)
  1300.                 {
  1301.                     struct MenuItem *Item;
  1302.  
  1303.                     while(MsgCode != MENUNULL)
  1304.                     {
  1305.                         if(Item = ItemAddress(Menu,MsgCode))
  1306.                         {
  1307.                             if(MENU_USERDATA(Item))
  1308.                             {
  1309.                                 if(!Result)
  1310.                                     Result = (int)MENU_USERDATA(Item);
  1311.                             }
  1312.  
  1313.                             MsgCode = Item->NextSelect;
  1314.                         }
  1315.                         else
  1316.                             break;
  1317.                     }
  1318.                 }
  1319.             }
  1320.  
  1321.             WindowReady = FALSE;
  1322.         }
  1323.  
  1324.         return(Result);
  1325.     }
  1326. }
  1327.  
  1328.     /* ConScanKey():
  1329.      *
  1330.      *    Check for a keyboard event.
  1331.      */
  1332.  
  1333. int
  1334. ConScanKey()
  1335. {
  1336.     if(ConsoleReady || WindowReady)
  1337.         return(1);
  1338.     else
  1339.     {
  1340.         int Result = 0;
  1341.  
  1342.         if(CheckSignal(SIG_WINDOW))
  1343.         {
  1344.             WindowReady = TRUE;
  1345.  
  1346.             Result = 1;
  1347.         }
  1348.  
  1349.         if(CheckIO(ConsoleReadRequest))
  1350.         {
  1351.             if(!WaitIO(ConsoleReadRequest))
  1352.             {
  1353.                 ConsoleReady = TRUE;
  1354.  
  1355.                 return(1);
  1356.             }
  1357.             else
  1358.             {
  1359.                 ConsoleReadRequest->io_Command    = CMD_READ;
  1360.                 ConsoleReadRequest->io_Data        = &ConsoleChar;
  1361.                 ConsoleReadRequest->io_Length    = 1;
  1362.  
  1363.                 ClrSignal(SIG_CONREAD);
  1364.                 SendIO(ConsoleReadRequest);
  1365.             }
  1366.         }
  1367.  
  1368.         return(Result);
  1369.     }
  1370.  
  1371.     return(0);
  1372. }
  1373.  
  1374.     /* dtr_out(byte flag):
  1375.      *
  1376.      *    If flag == 0->drop DTR signal, else set it.
  1377.      */
  1378.  
  1379. VOID
  1380. dtr_out(byte flag)
  1381. {
  1382.     if(!flag && !RendezvousData)
  1383.     {
  1384.         if(ThisBuffer->IsBusy)
  1385.         {
  1386.             WaitIO(ThisBuffer->SerialRequest);
  1387.  
  1388.             ThisBuffer->IsBusy        = FALSE;
  1389.             ThisBuffer->SerialIndex    = ThisBuffer->SerialBuffer;
  1390.         }
  1391.  
  1392.         if(ReadBuffer->IsBusy)
  1393.         {
  1394.             if(!CheckIO(ReadBuffer->SerialRequest))
  1395.                 AbortIO(ReadBuffer->SerialRequest);
  1396.  
  1397.             WaitIO(ReadBuffer->SerialRequest);
  1398.  
  1399.             ReadBuffer->IsBusy            = FALSE;
  1400.             ReadBuffer->SerialFilled    = ReadBuffer->SerialRequest->IOSer.io_Actual;
  1401.             ReadBuffer->SerialIndex        = ReadBuffer->SerialBuffer;
  1402.  
  1403.             ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
  1404.  
  1405.             DoIO(ReadBuffer->SerialRequest);
  1406.  
  1407.             if(ReadBuffer->SerialRequest->IOSer.io_Actual)
  1408.             {
  1409.                 LONG Size = ReadBuffer->SerialSize - ReadBuffer->SerialFilled;
  1410.  
  1411.                 if(Size > 0)
  1412.                 {
  1413.                     if(Size > ReadBuffer->SerialRequest->IOSer.io_Actual)
  1414.                         Size = ReadBuffer->SerialRequest->IOSer.io_Actual;
  1415.  
  1416.                     ReadBuffer->SerialRequest->IOSer.io_Command    = CMD_READ;
  1417.                     ReadBuffer->SerialRequest->IOSer.io_Data    = ReadBuffer->SerialBuffer + ReadBuffer->SerialFilled;
  1418.                     ReadBuffer->SerialRequest->IOSer.io_Length    = Size;
  1419.  
  1420.                     DoIO(ReadBuffer->SerialRequest);
  1421.  
  1422.                     ReadBuffer->SerialFilled += ReadBuffer->SerialRequest->IOSer.io_Actual;
  1423.                 }
  1424.             }
  1425.         }
  1426.  
  1427.         CloseDevice(ReadBuffer->SerialRequest);
  1428.  
  1429.         TimeRequest->tr_node.io_Command    = TR_ADDREQUEST;
  1430.         TimeRequest->tr_time.tv_secs    = 1;
  1431.         TimeRequest->tr_time.tv_micro    = 0;
  1432.  
  1433.         DoIO(TimeRequest);
  1434.  
  1435.         if(OpenDevice(device,port,ReadBuffer->SerialRequest,NULL))
  1436.         {
  1437.             CloseAll();
  1438.  
  1439.             exit(10);
  1440.         }
  1441.         else
  1442.         {
  1443.             ReadBuffer->SerialRequest->io_Baud        = ThisBuffer->SerialRequest->io_Baud;
  1444.             ReadBuffer->SerialRequest->io_ReadLen    = ThisBuffer->SerialRequest->io_ReadLen;
  1445.             ReadBuffer->SerialRequest->io_WriteLen    = ThisBuffer->SerialRequest->io_WriteLen;
  1446.             ReadBuffer->SerialRequest->io_SerFlags    = ThisBuffer->SerialRequest->io_SerFlags;
  1447.  
  1448.             ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_SETPARAMS;
  1449.  
  1450.             DoIO(ReadBuffer->SerialRequest);
  1451.  
  1452.             CopyMem(ReadBuffer->SerialRequest,ThisBuffer->SerialRequest,sizeof(struct IOExtSer));
  1453.  
  1454.             ThisBuffer->SerialRequest->IOSer.io_Message.mn_ReplyPort = WritePort;
  1455.  
  1456.             CopyMem(ReadBuffer->SerialRequest,NextBuffer->SerialRequest,sizeof(struct IOExtSer));
  1457.  
  1458.             NextBuffer->SerialRequest->IOSer.io_Message.mn_ReplyPort = WritePort;
  1459.         }
  1460.     }
  1461. }
  1462.  
  1463.     /* com_flow(byte flags):
  1464.      *
  1465.      *    The bit mask `flags' determines the style(s) of
  1466.      *    handshaking:
  1467.      *
  1468.      *    if (flags & 9)->enable xON/xOFF software handshaking,
  1469.      *    if (flags & 2)->enable RTS/CTS hardware handshaking
  1470.      */
  1471.  
  1472. VOID
  1473. com_flow(byte flags)
  1474. {
  1475.     if(ThisBuffer->IsBusy)
  1476.     {
  1477.         WaitIO(ThisBuffer->SerialRequest);
  1478.  
  1479.         ThisBuffer->IsBusy        = FALSE;
  1480.         ThisBuffer->SerialIndex    = ThisBuffer->SerialBuffer;
  1481.     }
  1482.  
  1483.     if(ReadBuffer->IsBusy)
  1484.     {
  1485.         if(!CheckIO(ReadBuffer->SerialRequest))
  1486.             AbortIO(ReadBuffer->SerialRequest);
  1487.  
  1488.         WaitIO(ReadBuffer->SerialRequest);
  1489.  
  1490.         ReadBuffer->IsBusy            = FALSE;
  1491.         ReadBuffer->SerialFilled    = ReadBuffer->SerialRequest->IOSer.io_Actual;
  1492.         ReadBuffer->SerialIndex        = ReadBuffer->SerialBuffer;
  1493.  
  1494.         ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
  1495.  
  1496.         DoIO(ReadBuffer->SerialRequest);
  1497.  
  1498.         if(ReadBuffer->SerialRequest->IOSer.io_Actual)
  1499.         {
  1500.             LONG Size = ReadBuffer->SerialSize - ReadBuffer->SerialFilled;
  1501.  
  1502.             if(Size > 0)
  1503.             {
  1504.                 if(Size > ReadBuffer->SerialRequest->IOSer.io_Actual)
  1505.                     Size = ReadBuffer->SerialRequest->IOSer.io_Actual;
  1506.  
  1507.                 ReadBuffer->SerialRequest->IOSer.io_Command    = CMD_READ;
  1508.                 ReadBuffer->SerialRequest->IOSer.io_Data    = ReadBuffer->SerialBuffer + ReadBuffer->SerialFilled;
  1509.                 ReadBuffer->SerialRequest->IOSer.io_Length    = Size;
  1510.  
  1511.                 DoIO(ReadBuffer->SerialRequest);
  1512.  
  1513.                 ReadBuffer->SerialFilled += ReadBuffer->SerialRequest->IOSer.io_Actual;
  1514.             }
  1515.         }
  1516.     }
  1517.  
  1518.     if(flags & 2)
  1519.         ReadBuffer->SerialRequest->io_SerFlags |= SERF_7WIRE;
  1520.     else
  1521.         ReadBuffer->SerialRequest->io_SerFlags &= ~SERF_7WIRE;
  1522.  
  1523.     if(flags & 9)
  1524.         ReadBuffer->SerialRequest->io_SerFlags &= ~SERF_XDISABLED;
  1525.     else
  1526.         ReadBuffer->SerialRequest->io_SerFlags |= SERF_XDISABLED;
  1527.  
  1528.     ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_SETPARAMS;
  1529.  
  1530.     DoIO(ReadBuffer->SerialRequest);
  1531.  
  1532.     ThisBuffer->SerialRequest->io_SerFlags = ReadBuffer->SerialRequest->io_SerFlags;
  1533.     NextBuffer->SerialRequest->io_SerFlags = ReadBuffer->SerialRequest->io_SerFlags;
  1534. }
  1535.  
  1536.     /* com_setspeed(word speed):
  1537.      *
  1538.      *    Set the transfer speed (in bits/second).
  1539.      */
  1540.  
  1541. VOID
  1542. com_setspeed(word speed)
  1543. {
  1544.     if(ThisBuffer->IsBusy)
  1545.     {
  1546.         WaitIO(ThisBuffer->SerialRequest);
  1547.  
  1548.         ThisBuffer->IsBusy        = FALSE;
  1549.         ThisBuffer->SerialIndex    = ThisBuffer->SerialBuffer;
  1550.     }
  1551.  
  1552.     if(ReadBuffer->IsBusy)
  1553.     {
  1554.         if(!CheckIO(ReadBuffer->SerialRequest))
  1555.             AbortIO(ReadBuffer->SerialRequest);
  1556.  
  1557.         WaitIO(ReadBuffer->SerialRequest);
  1558.  
  1559.         ReadBuffer->IsBusy            = FALSE;
  1560.         ReadBuffer->SerialFilled    = ReadBuffer->SerialRequest->IOSer.io_Actual;
  1561.         ReadBuffer->SerialIndex        = ReadBuffer->SerialBuffer;
  1562.  
  1563.         ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
  1564.  
  1565.         DoIO(ReadBuffer->SerialRequest);
  1566.  
  1567.         if(ReadBuffer->SerialRequest->IOSer.io_Actual)
  1568.         {
  1569.             LONG Size = ReadBuffer->SerialSize - ReadBuffer->SerialFilled;
  1570.  
  1571.             if(Size > 0)
  1572.             {
  1573.                 if(Size > ReadBuffer->SerialRequest->IOSer.io_Actual)
  1574.                     Size = ReadBuffer->SerialRequest->IOSer.io_Actual;
  1575.  
  1576.                 ReadBuffer->SerialRequest->IOSer.io_Command    = CMD_READ;
  1577.                 ReadBuffer->SerialRequest->IOSer.io_Data    = ReadBuffer->SerialBuffer + ReadBuffer->SerialFilled;
  1578.                 ReadBuffer->SerialRequest->IOSer.io_Length    = Size;
  1579.  
  1580.                 DoIO(ReadBuffer->SerialRequest);
  1581.  
  1582.                 ReadBuffer->SerialFilled += ReadBuffer->SerialRequest->IOSer.io_Actual;
  1583.             }
  1584.         }
  1585.     }
  1586.  
  1587.     ReadBuffer->SerialRequest->io_Baud = speed;
  1588.  
  1589.     if(parity)
  1590.     {
  1591.         ReadBuffer->SerialRequest->io_ReadLen = ReadBuffer->SerialRequest->io_WriteLen = 7;
  1592.         ReadBuffer->SerialRequest->io_SerFlags |= SERF_PARTY_ON;
  1593.     }
  1594.     else
  1595.     {
  1596.         ReadBuffer->SerialRequest->io_ReadLen = ReadBuffer->SerialRequest->io_WriteLen = 8;
  1597.         ReadBuffer->SerialRequest->io_SerFlags &= ~SERF_PARTY_ON;
  1598.     }
  1599.  
  1600.     ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_SETPARAMS;
  1601.  
  1602.     DoIO(ReadBuffer->SerialRequest);
  1603.  
  1604.     ThisBuffer->SerialRequest->io_Baud        = ReadBuffer->SerialRequest->io_Baud;
  1605.     ThisBuffer->SerialRequest->io_ReadLen    = ReadBuffer->SerialRequest->io_ReadLen;
  1606.     ThisBuffer->SerialRequest->io_WriteLen    = ReadBuffer->SerialRequest->io_WriteLen;
  1607.     ThisBuffer->SerialRequest->io_SerFlags    = ReadBuffer->SerialRequest->io_SerFlags;
  1608.  
  1609.     NextBuffer->SerialRequest->io_Baud        = ReadBuffer->SerialRequest->io_Baud;
  1610.     NextBuffer->SerialRequest->io_ReadLen    = ReadBuffer->SerialRequest->io_ReadLen;
  1611.     NextBuffer->SerialRequest->io_WriteLen    = ReadBuffer->SerialRequest->io_WriteLen;
  1612.     NextBuffer->SerialRequest->io_SerFlags    = ReadBuffer->SerialRequest->io_SerFlags;
  1613. }
  1614.  
  1615.     /* com_putblock(byte *s,word len):
  1616.      *
  1617.      *    Send a data block asynchronously.
  1618.      */
  1619.  
  1620. VOID
  1621. com_putblock(byte *s,word len)
  1622. {
  1623.     struct SerialBuffer *Swap = ThisBuffer;
  1624.  
  1625.     if(ThisBuffer->IsBusy)
  1626.         WaitIO(ThisBuffer->SerialRequest);
  1627.     else
  1628.     {
  1629.         if(ThisBuffer->SerialIndex > ThisBuffer->SerialBuffer)
  1630.         {
  1631.             ThisBuffer->SerialRequest->IOSer.io_Command    = CMD_WRITE;
  1632.             ThisBuffer->SerialRequest->IOSer.io_Data    = ThisBuffer->SerialBuffer;
  1633.             ThisBuffer->SerialRequest->IOSer.io_Length    = ThisBuffer->SerialIndex - ThisBuffer->SerialBuffer;
  1634.  
  1635.             DoIO(ThisBuffer->SerialRequest);
  1636.         }
  1637.     }
  1638.  
  1639.     ThisBuffer->IsBusy        = FALSE;
  1640.     ThisBuffer->SerialIndex    = ThisBuffer->SerialBuffer;
  1641.  
  1642.     ThisBuffer = NextBuffer;
  1643.     NextBuffer = Swap;
  1644.  
  1645.     if(ThisBuffer->SerialIndex > ThisBuffer->SerialBuffer)
  1646.     {
  1647.         ThisBuffer->SerialRequest->IOSer.io_Command    = CMD_WRITE;
  1648.         ThisBuffer->SerialRequest->IOSer.io_Data    = ThisBuffer->SerialBuffer;
  1649.         ThisBuffer->SerialRequest->IOSer.io_Length    = ThisBuffer->SerialIndex - ThisBuffer->SerialBuffer;
  1650.  
  1651.         DoIO(ThisBuffer->SerialRequest);
  1652.     }
  1653.  
  1654.     ThisBuffer->IsBusy        = FALSE;
  1655.     ThisBuffer->SerialIndex    = ThisBuffer->SerialBuffer;
  1656.  
  1657.     while(len > 2 * ThisBuffer->SerialSize)
  1658.     {
  1659.         ThisBuffer->SerialRequest->IOSer.io_Command    = CMD_WRITE;
  1660.         ThisBuffer->SerialRequest->IOSer.io_Data    = s;
  1661.         ThisBuffer->SerialRequest->IOSer.io_Length    = ThisBuffer->SerialSize;
  1662.  
  1663.         s    += ThisBuffer->SerialSize;
  1664.         len    -= ThisBuffer->SerialSize;
  1665.  
  1666.         DoIO(ThisBuffer->SerialRequest);
  1667.     }
  1668.  
  1669.     CopyMem(s,ThisBuffer->SerialBuffer,MIN(len,ThisBuffer->SerialSize));
  1670.  
  1671.     ThisBuffer->IsBusy                            = TRUE;
  1672.     ThisBuffer->SerialIndex                        = ThisBuffer->SerialBuffer + MIN(len,ThisBuffer->SerialSize);
  1673.     ThisBuffer->SerialRequest->IOSer.io_Command    = CMD_WRITE;
  1674.     ThisBuffer->SerialRequest->IOSer.io_Data    = ThisBuffer->SerialBuffer;
  1675.     ThisBuffer->SerialRequest->IOSer.io_Length    = MIN(len,ThisBuffer->SerialSize);
  1676.  
  1677.     len    -= ThisBuffer->SerialRequest->IOSer.io_Length;
  1678.     s    += ThisBuffer->SerialRequest->IOSer.io_Length;
  1679.  
  1680.     ClrSignal(SIG_SERWRITE);
  1681.     SendIO(ThisBuffer->SerialRequest);
  1682.  
  1683.     if(len > 0)
  1684.     {
  1685.         CopyMem(s,NextBuffer->SerialBuffer,len);
  1686.  
  1687.         NextBuffer->SerialIndex = NextBuffer->SerialBuffer + len;
  1688.     }
  1689. }
  1690.  
  1691.     /* breakfunc():
  1692.      *
  1693.      *    Cleanup routine for SAS/C.
  1694.      */
  1695.  
  1696. static int
  1697. breakfunc(void)
  1698. {
  1699.     CloseAll();
  1700.  
  1701.     return(1);
  1702. }
  1703.  
  1704.     /* sys_init(VOID):
  1705.      *
  1706.      *    Initialize this driver implementation.
  1707.      */
  1708.  
  1709. VOID
  1710. sys_init(VOID)
  1711. {
  1712.     if(!OpenAll(device,port))
  1713.     {
  1714.         CloseAll();
  1715.  
  1716.         endprog(2);
  1717.     }
  1718.  
  1719.     onbreak(breakfunc);
  1720. }
  1721.  
  1722.     /* sys_reset(VOID):
  1723.      *
  1724.      *    Perform cleanup for this driver implementation.
  1725.      */
  1726.  
  1727. VOID
  1728. sys_reset(VOID)
  1729. {
  1730.     CloseAll();
  1731. }
  1732.  
  1733.     /* sys_idle(VOID):
  1734.      *
  1735.      *    This routine gets called when the system is idle.
  1736.      *    That's a nice one. We are supposed to call the
  1737.      *    system scheduler, etc.
  1738.      */
  1739.  
  1740. VOID
  1741. sys_idle(VOID)
  1742. {
  1743.     ULONG Signals;
  1744.  
  1745.     if(ReadBuffer->SerialFilled <= 0 && !ReadBuffer->IsBusy)
  1746.     {
  1747.         ReadBuffer->IsBusy                            = TRUE;
  1748.         ReadBuffer->SerialIndex                        = ReadBuffer->SerialBuffer;
  1749.         ReadBuffer->SerialRequest->IOSer.io_Command    = CMD_READ;
  1750.         ReadBuffer->SerialRequest->IOSer.io_Data    = ReadBuffer->SerialBuffer;
  1751.         ReadBuffer->SerialRequest->IOSer.io_Length    = 1;
  1752.  
  1753.         ClrSignal(SIG_SERREAD);
  1754.         SendIO(ReadBuffer->SerialRequest);
  1755.     }
  1756.  
  1757.     TimeRequest->tr_node.io_Command    = TR_ADDREQUEST;
  1758.     TimeRequest->tr_time.tv_secs    = 1;
  1759.     TimeRequest->tr_time.tv_micro    = 0;
  1760.  
  1761.     ClrSignal(SIG_TIMER);
  1762.     SendIO(TimeRequest);
  1763.  
  1764.     Signals = Wait(SIG_SERREAD | SIG_SERWRITE | SIG_CONREAD | SIG_WINDOW | SIG_TIMER);
  1765.  
  1766.     if(!(Signals & SIG_TIMER))
  1767.     {
  1768.         if(!CheckIO(TimeRequest))
  1769.             AbortIO(TimeRequest);
  1770.     }
  1771.  
  1772.     WaitIO(TimeRequest);
  1773.  
  1774.     if(Signals & SIG_SERREAD)
  1775.     {
  1776.         WaitIO(ReadBuffer->SerialRequest);
  1777.  
  1778.         ReadBuffer->IsBusy            = FALSE;
  1779.         ReadBuffer->SerialFilled    = ReadBuffer->SerialRequest->IOSer.io_Actual;
  1780.         ReadBuffer->SerialIndex        = ReadBuffer->SerialBuffer;
  1781.  
  1782.         ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
  1783.  
  1784.         DoIO(ReadBuffer->SerialRequest);
  1785.  
  1786.         if(ReadBuffer->SerialRequest->IOSer.io_Actual)
  1787.         {
  1788.             LONG Size = ReadBuffer->SerialSize - ReadBuffer->SerialFilled;
  1789.  
  1790.             if(Size > 0)
  1791.             {
  1792.                 if(Size > ReadBuffer->SerialRequest->IOSer.io_Actual)
  1793.                     Size = ReadBuffer->SerialRequest->IOSer.io_Actual;
  1794.  
  1795.                 ReadBuffer->SerialRequest->IOSer.io_Command    = CMD_READ;
  1796.                 ReadBuffer->SerialRequest->IOSer.io_Data    = ReadBuffer->SerialBuffer + ReadBuffer->SerialFilled;
  1797.                 ReadBuffer->SerialRequest->IOSer.io_Length    = Size;
  1798.  
  1799.                 DoIO(ReadBuffer->SerialRequest);
  1800.  
  1801.                 ReadBuffer->SerialFilled += ReadBuffer->SerialRequest->IOSer.io_Actual;
  1802.             }
  1803.         }
  1804.     }
  1805.  
  1806.     if(Signals & SIG_SERWRITE)
  1807.     {
  1808.         struct SerialBuffer *Swap = ThisBuffer;
  1809.  
  1810.         WaitIO(ThisBuffer->SerialRequest);
  1811.  
  1812.         ThisBuffer->IsBusy        = FALSE;
  1813.         ThisBuffer->SerialIndex    = ThisBuffer->SerialBuffer;
  1814.  
  1815.         ThisBuffer = NextBuffer;
  1816.         NextBuffer = Swap;
  1817.     }
  1818.  
  1819.     if(Signals & SIG_CONREAD)
  1820.     {
  1821.         WaitIO(ConsoleReadRequest);
  1822.  
  1823.         ConsoleReady = TRUE;
  1824.     }
  1825.  
  1826.     if(Signals & SIG_WINDOW)
  1827.         WindowReady = TRUE;
  1828. }
  1829.  
  1830.     /* com_outfull(VOID):
  1831.      *
  1832.      *    Return number of bytes still to be transferred.
  1833.      */
  1834.  
  1835. int
  1836. com_outfull(VOID)
  1837. {
  1838.     return(ThisBuffer->SerialIndex - ThisBuffer->SerialBuffer + NextBuffer->SerialIndex - NextBuffer->SerialBuffer);
  1839. }
  1840.  
  1841.     /* carrier(VOID):
  1842.      *
  1843.      *    Return current carrier status.
  1844.      */
  1845.  
  1846. int
  1847. carrier(VOID)
  1848. {
  1849.     if(nocarrier)
  1850.         return(1);
  1851.     else
  1852.     {
  1853.         if(!ThisBuffer->IsBusy)
  1854.         {
  1855.             ThisBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
  1856.  
  1857.             DoIO(ThisBuffer->SerialRequest);
  1858.  
  1859.             if(ThisBuffer->SerialRequest->io_Status & CIAF_COMCD)
  1860.                 return(0);
  1861.             else
  1862.                 return(1);
  1863.         }
  1864.         else
  1865.         {
  1866.             NextBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
  1867.  
  1868.             DoIO(NextBuffer->SerialRequest);
  1869.  
  1870.             if(NextBuffer->SerialRequest->io_Status & CIAF_COMCD)
  1871.                 return(0);
  1872.             else
  1873.                 return(1);
  1874.         }
  1875.     }
  1876. }
  1877.  
  1878.     /* com_flush(VOID):
  1879.      *
  1880.      *    Make sure all pending data gets written.
  1881.      */
  1882.  
  1883. VOID
  1884. com_flush(VOID)
  1885. {
  1886.     if(ThisBuffer->IsBusy)
  1887.     {
  1888.         WaitIO(ThisBuffer->SerialRequest);
  1889.  
  1890.         ThisBuffer->IsBusy        = FALSE;
  1891.         ThisBuffer->SerialIndex    = ThisBuffer->SerialBuffer;
  1892.     }
  1893.  
  1894.     if(NextBuffer->SerialIndex > NextBuffer->SerialBuffer)
  1895.     {
  1896.         NextBuffer->SerialRequest->IOSer.io_Command    = CMD_WRITE;
  1897.         NextBuffer->SerialRequest->IOSer.io_Data    = NextBuffer->SerialBuffer;
  1898.         NextBuffer->SerialRequest->IOSer.io_Length    = NextBuffer->SerialIndex - NextBuffer->SerialBuffer;
  1899.  
  1900.         DoIO(NextBuffer->SerialRequest);
  1901.  
  1902.         NextBuffer->SerialIndex = NextBuffer->SerialBuffer;
  1903.     }
  1904. }
  1905.  
  1906.     /* com_putbyte(byte c):
  1907.      *
  1908.      *    Transmit a single byte, queueing it if necessary.
  1909.      */
  1910.  
  1911. VOID
  1912. com_putbyte(byte c)
  1913. {
  1914.     if(ThisBuffer->IsBusy)
  1915.     {
  1916.         if(NextBuffer->SerialIndex + 1 >= NextBuffer->SerialTop)
  1917.         {
  1918.             struct SerialBuffer *Swap = ThisBuffer;
  1919.  
  1920.             WaitIO(ThisBuffer->SerialRequest);
  1921.  
  1922.             ThisBuffer->IsBusy        = FALSE;
  1923.             ThisBuffer->SerialIndex    = ThisBuffer->SerialBuffer;
  1924.  
  1925.             ThisBuffer = NextBuffer;
  1926.             NextBuffer = Swap;
  1927.  
  1928.             ThisBuffer->IsBusy                            = TRUE;
  1929.             ThisBuffer->SerialRequest->IOSer.io_Command    = CMD_WRITE;
  1930.             ThisBuffer->SerialRequest->IOSer.io_Data    = ThisBuffer->SerialBuffer;
  1931.             ThisBuffer->SerialRequest->IOSer.io_Length    = ThisBuffer->SerialIndex - ThisBuffer->SerialBuffer;
  1932.  
  1933.             ClrSignal(SIG_SERWRITE);
  1934.             SendIO(ThisBuffer->SerialRequest);
  1935.         }
  1936.  
  1937.         *NextBuffer->SerialIndex++ = c;
  1938.     }
  1939.     else
  1940.     {
  1941.         if(ThisBuffer->SerialIndex + 1 < ThisBuffer->SerialTop)
  1942.         {
  1943.             *ThisBuffer->SerialIndex++ = c;
  1944.  
  1945.             ThisBuffer->IsBusy                            = TRUE;
  1946.             ThisBuffer->SerialRequest->IOSer.io_Command    = CMD_WRITE;
  1947.             ThisBuffer->SerialRequest->IOSer.io_Data    = ThisBuffer->SerialBuffer;
  1948.             ThisBuffer->SerialRequest->IOSer.io_Length    = 1;
  1949.  
  1950.             ClrSignal(SIG_SERWRITE);
  1951.             SendIO(ThisBuffer->SerialRequest);
  1952.         }
  1953.         else
  1954.         {
  1955.             ThisBuffer->IsBusy                            = TRUE;
  1956.             ThisBuffer->SerialRequest->IOSer.io_Command    = CMD_WRITE;
  1957.             ThisBuffer->SerialRequest->IOSer.io_Data    = ThisBuffer->SerialBuffer;
  1958.             ThisBuffer->SerialRequest->IOSer.io_Length    = ThisBuffer->SerialIndex - ThisBuffer->SerialBuffer;
  1959.  
  1960.             ClrSignal(SIG_SERWRITE);
  1961.             SendIO(ThisBuffer->SerialRequest);
  1962.  
  1963.             *NextBuffer->SerialIndex++ = c;
  1964.         }
  1965.     }
  1966. }
  1967.  
  1968.     /* com_purge(VOID):
  1969.      *
  1970.      *    Clear the read/write buffers.
  1971.      */
  1972.  
  1973. VOID
  1974. com_purge(VOID)
  1975. {
  1976.     if(ThisBuffer->IsBusy)
  1977.     {
  1978.         if(!CheckIO(ThisBuffer->SerialRequest))
  1979.             AbortIO(ThisBuffer->SerialRequest);
  1980.  
  1981.         WaitIO(ThisBuffer->SerialRequest);
  1982.     }
  1983.  
  1984.     ThisBuffer->IsBusy        = FALSE;
  1985.     ThisBuffer->SerialIndex    = ThisBuffer->SerialBuffer;
  1986.  
  1987.     NextBuffer->IsBusy        = FALSE;
  1988.     NextBuffer->SerialIndex    = NextBuffer->SerialBuffer;
  1989.  
  1990.     if(ReadBuffer->IsBusy)
  1991.     {
  1992.         if(!CheckIO(ReadBuffer->SerialRequest))
  1993.             AbortIO(ReadBuffer->SerialRequest);
  1994.  
  1995.         WaitIO(ReadBuffer->SerialRequest);
  1996.     }
  1997.  
  1998.     ReadBuffer->IsBusy            = FALSE;
  1999.     ReadBuffer->SerialIndex        = ReadBuffer->SerialBuffer;
  2000.     ReadBuffer->SerialFilled    = 0;
  2001.  
  2002.     ThisBuffer->SerialRequest->IOSer.io_Command = CMD_CLEAR;
  2003.     DoIO(ThisBuffer->SerialRequest);
  2004. }
  2005.  
  2006.     /* com_dump(VOID):
  2007.      *
  2008.      *    Wait for asynchronous write request to terminate.
  2009.      */
  2010.  
  2011. VOID
  2012. com_dump(VOID)
  2013. {
  2014.     com_flush();
  2015. }
  2016.  
  2017.     /* com_getbyte(VOID):
  2018.      *
  2019.      *    Read a single byte from the serial line. If not available,
  2020.      *    return EOF.
  2021.      */
  2022.  
  2023. int
  2024. com_getbyte(VOID)
  2025. {
  2026.     int Result;
  2027.  
  2028.     if(ReadBuffer->SerialFilled <= 0)
  2029.     {
  2030.         if(ReadBuffer->IsBusy)
  2031.         {
  2032.             if(!CheckIO(ReadBuffer->SerialRequest))
  2033.                 return(EOF);
  2034.             else
  2035.                 WaitIO(ReadBuffer->SerialRequest);
  2036.  
  2037.             ReadBuffer->IsBusy            = FALSE;
  2038.             ReadBuffer->SerialFilled    = ReadBuffer->SerialRequest->IOSer.io_Actual;
  2039.             ReadBuffer->SerialIndex        = ReadBuffer->SerialBuffer;
  2040.  
  2041.             ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
  2042.  
  2043.             DoIO(ReadBuffer->SerialRequest);
  2044.  
  2045.             if(ReadBuffer->SerialRequest->IOSer.io_Actual)
  2046.             {
  2047.                 LONG Size = ReadBuffer->SerialSize - ReadBuffer->SerialFilled;
  2048.  
  2049.                 if(Size > 0)
  2050.                 {
  2051.                     if(Size > ReadBuffer->SerialRequest->IOSer.io_Actual)
  2052.                         Size = ReadBuffer->SerialRequest->IOSer.io_Actual;
  2053.  
  2054.                     ReadBuffer->SerialRequest->IOSer.io_Command    = CMD_READ;
  2055.                     ReadBuffer->SerialRequest->IOSer.io_Data    = ReadBuffer->SerialBuffer + ReadBuffer->SerialFilled;
  2056.                     ReadBuffer->SerialRequest->IOSer.io_Length    = Size;
  2057.  
  2058.                     DoIO(ReadBuffer->SerialRequest);
  2059.  
  2060.                     ReadBuffer->SerialFilled += ReadBuffer->SerialRequest->IOSer.io_Actual;
  2061.                 }
  2062.             }
  2063.         }
  2064.         else
  2065.         {
  2066.             ReadBuffer->SerialRequest->IOSer.io_Command = SDCMD_QUERY;
  2067.  
  2068.             DoIO(ReadBuffer->SerialRequest);
  2069.  
  2070.             if(!ReadBuffer->SerialRequest->IOSer.io_Actual)
  2071.                 return(EOF);
  2072.             else
  2073.             {
  2074.                 ReadBuffer->SerialRequest->IOSer.io_Command    = CMD_READ;
  2075.                 ReadBuffer->SerialRequest->IOSer.io_Data    = ReadBuffer->SerialBuffer;
  2076.                 ReadBuffer->SerialRequest->IOSer.io_Length    = MIN(ReadBuffer->SerialRequest->IOSer.io_Actual,ReadBuffer->SerialSize);
  2077.  
  2078.                 DoIO(ReadBuffer->SerialRequest);
  2079.  
  2080.                 if(!ReadBuffer->SerialRequest->IOSer.io_Actual)
  2081.                     return(EOF);
  2082.                 else
  2083.                 {
  2084.                     ReadBuffer->SerialFilled    = ReadBuffer->SerialRequest->IOSer.io_Actual;
  2085.                     ReadBuffer->SerialIndex        = ReadBuffer->SerialBuffer;
  2086.                 }
  2087.             }
  2088.         }
  2089.     }
  2090.  
  2091.     Result = *ReadBuffer->SerialIndex++;
  2092.  
  2093.     ReadBuffer->SerialFilled--;
  2094.  
  2095.     if(ReadBuffer->SerialFilled <= 0)
  2096.     {
  2097.         ReadBuffer->IsBusy                    = TRUE;
  2098.         ReadBuffer->SerialIndex                = ReadBuffer->SerialBuffer;
  2099.  
  2100.         ReadBuffer->SerialRequest->IOSer.io_Command    = CMD_READ;
  2101.         ReadBuffer->SerialRequest->IOSer.io_Data    = ReadBuffer->SerialBuffer;
  2102.         ReadBuffer->SerialRequest->IOSer.io_Length    = 1;
  2103.  
  2104.         ClrSignal(SIG_SERREAD);
  2105.         SendIO(ReadBuffer->SerialRequest);
  2106.     }
  2107.  
  2108.     return(Result);
  2109. }
  2110.  
  2111.     /* setstamp(STRPTR Name,LONG Time):
  2112.      *
  2113.      *    Set time/date of a file.
  2114.      */
  2115.  
  2116. VOID
  2117. setstamp(char *Name,long Time)
  2118. {
  2119.     struct DateStamp Date;
  2120.     ULONG Seconds;
  2121.  
  2122.     DB(kprintf("setstamp |%s| %ld\n",Name,Time));
  2123.  
  2124.         /* Translate it into an Amiga date. */
  2125.  
  2126.     if(Time > GMT_Offset)
  2127.         Seconds = Time - GMT_Offset;
  2128.     else
  2129.         Seconds = 0;
  2130.  
  2131.     Date.ds_Days    = Seconds / (24 * 60 * 60);
  2132.     Date.ds_Minute    = (Seconds % (24 * 60 * 60)) / 60;
  2133.     Date.ds_Tick    = (Seconds % 60) * TICKS_PER_SECOND;
  2134.  
  2135.     SetFileDate(Name,&Date);
  2136. }
  2137.  
  2138.     /* freespace(STRPTR DrivePath):
  2139.      *
  2140.      *    Get free disk space for specified drive.
  2141.      */
  2142.  
  2143. long
  2144. freespace(char *DrivePath)
  2145. {
  2146.     struct DevProc    *DevProc;
  2147.     struct DosList    *DosList;
  2148.     BOOL             GoodDevice;
  2149.     LONG             Size;
  2150.  
  2151.     if(!DrivePath)
  2152.         DrivePath = "";
  2153.  
  2154.     DB(kprintf("freespace |%s|\n",DrivePath));
  2155.  
  2156.     DevProc = GetDeviceProc(DrivePath,NULL);
  2157.  
  2158.     GoodDevice = FALSE;
  2159.     Size = (LONG)((ULONG)~0 >> 2);
  2160.  
  2161.     if(DosList = LockDosList(LDF_DEVICES | LDF_READ))
  2162.     {
  2163.         while(DosList = NextDosEntry(DosList,LDF_DEVICES))
  2164.         {
  2165.             if(DosList->dol_Task == DevProc->dvp_Port)
  2166.             {
  2167.                 struct FileSysStartupMsg *FSSM = (struct FileSysStartupMsg *)BADDR(DosList->dol_misc.dol_handler.dol_Startup);
  2168.  
  2169.                 if(TypeOfMem(FSSM))
  2170.                 {
  2171.                     struct DosEnvec *DosEnvec = (struct DosEnvec *)BADDR(FSSM->fssm_Environ);
  2172.                     STRPTR Name = (STRPTR)BADDR(FSSM->fssm_Device);
  2173.  
  2174.                     if(TypeOfMem(DosEnvec) && TypeOfMem(Name))
  2175.                     {
  2176.                         if(Name[0] > 0 && !Name[(WORD)Name[0] + 1])
  2177.                         {
  2178.                             struct IOStdReq IORequest;
  2179.  
  2180.                             memset(&IORequest,0,sizeof(IORequest));
  2181.                             IORequest.io_Message.mn_Length = sizeof(IORequest);
  2182.  
  2183.                             if(!OpenDevice(Name + 1,FSSM->fssm_Unit,&IORequest,FSSM->fssm_Unit))
  2184.                             {
  2185.                                 CloseDevice(&IORequest);
  2186.  
  2187.                                 if(DosEnvec->de_TableSize > 0 && DosEnvec->de_LowCyl <= DosEnvec->de_HighCyl)
  2188.                                     GoodDevice = TRUE;
  2189.                             }
  2190.                         }
  2191.                     }
  2192.                 }
  2193.             }
  2194.         }
  2195.  
  2196.         UnLockDosList(LDF_DEVICES | LDF_READ);
  2197.     }
  2198.  
  2199.     FreeDeviceProc(DevProc);
  2200.  
  2201.     if(GoodDevice)
  2202.     {
  2203.         struct InfoData *InfoData;
  2204.  
  2205.         if(InfoData = (struct InfoData *)AllocVec(sizeof(struct InfoData),MEMF_ANY | MEMF_PUBLIC))
  2206.         {
  2207.             UBYTE NewName[MAX_FILENAME_LENGTH],*Index;
  2208.             BPTR FileLock;
  2209.  
  2210.             memcpy(NewName,DrivePath,sizeof(NewName) - 1);
  2211.  
  2212.             NewName[sizeof(NewName) - 1] = 0;
  2213.  
  2214.             Index = PathPart(NewName);
  2215.  
  2216.             *Index = 0;
  2217.  
  2218.             FileLock = Lock(NewName,ACCESS_READ);
  2219.  
  2220.             if(FileLock)
  2221.             {
  2222.                 if(Info(FileLock,InfoData))
  2223.                     Size = InfoData->id_BytesPerBlock * (InfoData->id_NumBlocks - InfoData->id_NumBlocksUsed);
  2224.  
  2225.                 UnLock(FileLock);
  2226.             }
  2227.  
  2228.             FreeVec(InfoData);
  2229.         }
  2230.     }
  2231.  
  2232.     return(Size);
  2233. }
  2234.  
  2235.     /* ffirst(char *FileSpec):
  2236.      *
  2237.      *    Return name of first file matching the given specs.
  2238.      */
  2239.  
  2240. char *
  2241. ffirst(char *filespec)
  2242. {
  2243.     AnchorUsed = TRUE;
  2244.  
  2245.     DB(kprintf("ffirst |%s|\n",filespec));
  2246.  
  2247.     if(MatchFirst(filespec,Anchor))
  2248.         return(NULL);
  2249.     else
  2250.         return((char *)Anchor->ap_Buf);
  2251. }
  2252.  
  2253.     /* fnext(VOID):
  2254.      *
  2255.      *    Return name of next file matching the given specs.
  2256.      */
  2257.  
  2258. char *
  2259. fnext(VOID)
  2260. {
  2261.     AnchorUsed = TRUE;
  2262.  
  2263.     DB(kprintf("fnext\n"));
  2264.  
  2265.     if(MatchNext(Anchor))
  2266.         return(NULL);
  2267.     else
  2268.         return((char *)Anchor->ap_Buf);
  2269. }
  2270.  
  2271.     /* time(time_t *timeptr):
  2272.      *
  2273.      *    Get the current time.
  2274.      */
  2275.  
  2276. time_t
  2277. time(time_t *timeptr)
  2278. {
  2279.     struct timeval    Now;
  2280.     time_t            CurrentTime;
  2281.  
  2282.     DB(kprintf("time 0x%08lx\n",timeptr));
  2283.  
  2284.         /* If the timer is already available,
  2285.          * just read the time. Otherwise, open what
  2286.          * we need to tell the time.
  2287.          */
  2288.  
  2289.     if(TimerBase)
  2290.         GetSysTime(&Now);
  2291.     else
  2292.         UpdateTime(&Now);
  2293.  
  2294.         /* Determine the current time, taking the time
  2295.          * zone into account.
  2296.          */
  2297.  
  2298.     CurrentTime = (time_t)(Now.tv_secs + GMT_Offset);
  2299.  
  2300.     if(timeptr)
  2301.         *timeptr = CurrentTime;
  2302.  
  2303.     return(CurrentTime);
  2304. }
  2305.  
  2306.     /* localtime(const time_t *t):
  2307.      *
  2308.      *    Convert UTC into local time.
  2309.      */
  2310.  
  2311. struct tm *
  2312. localtime(const time_t *t)
  2313. {
  2314.     STATIC struct tm Time;
  2315.  
  2316.     ULONG                Seconds,
  2317.                         Delta;
  2318.     struct ClockData    ClockData;
  2319.     BOOL                CloseIt = FALSE;
  2320.  
  2321.     DB(kprintf("localtime 0x%08lx\n",t));
  2322.  
  2323.         /* We need utility.library for the date conversion. */
  2324.  
  2325.     if(!UtilityBase)
  2326.     {
  2327.         if(UtilityBase = OpenLibrary("utility.library",37))
  2328.             CloseIt = TRUE;
  2329.     }
  2330.  
  2331.         /* Any luck? */
  2332.  
  2333.     if(!UtilityBase)
  2334.     {
  2335.         memset(&Time,0,sizeof(struct tm));
  2336.  
  2337.         return(&Time);
  2338.     }
  2339.  
  2340.         /* Update the time data. */
  2341.  
  2342.     if(!TimerBase)
  2343.         UpdateTime(NULL);
  2344.  
  2345.         /* Add the offset. */
  2346.  
  2347.     if(*t < GMT_Offset)
  2348.         Seconds = 0;
  2349.     else
  2350.         Seconds = (ULONG)*t - GMT_Offset;
  2351.  
  2352.         /* Convert the seconds into time data. */
  2353.  
  2354.     Amiga2Date(Seconds,&ClockData);
  2355.  
  2356.         /* Convert the time data. */
  2357.  
  2358.     Time.tm_sec        = ClockData.sec;
  2359.     Time.tm_min        = ClockData.min;
  2360.     Time.tm_hour    = ClockData.hour;
  2361.     Time.tm_mday    = ClockData.mday;
  2362.     Time.tm_mon        = ClockData.month - 1;
  2363.     Time.tm_year    = ClockData.year - 1900;
  2364.     Time.tm_wday    = ClockData.wday;
  2365.  
  2366.         /* No daylight savings time info is provided. */
  2367.  
  2368.     Time.tm_isdst = 0;
  2369.  
  2370.         /* We will need to fill in the yday entry. */
  2371.  
  2372.     ClockData.mday    = 1;
  2373.     ClockData.month    = 1;
  2374.  
  2375.     Delta = Date2Amiga(&ClockData);
  2376.  
  2377.     Time.tm_yday = (Seconds - Delta) / (24 * 60 * 60) + 1;
  2378.  
  2379.         /* Clean up if necessary. */
  2380.  
  2381.     if(CloseIt)
  2382.     {
  2383.         CloseLibrary(UtilityBase);
  2384.  
  2385.         UtilityBase = NULL;
  2386.     }
  2387.  
  2388.     return(&Time);
  2389. }
  2390.  
  2391.     /* stat(const char *file,struct stat *st):
  2392.      *
  2393.      *    Get information on a file.
  2394.      */
  2395.  
  2396. int
  2397. stat(const char *file,struct stat *st)
  2398. {
  2399.     BPTR FileLock;
  2400.     D_S(struct FileInfoBlock,FileInfo);
  2401.  
  2402.     DB(kprintf("stat |%s| 0%08lx\n",file,st));
  2403.  
  2404.         /* Try to get a lock on the file. */
  2405.  
  2406.     if(FileLock = Lock((STRPTR)file,ACCESS_READ))
  2407.     {
  2408.         STATIC char    Volume[MAX_FILENAME_LENGTH],Comment[80];
  2409.         D_S(struct InfoData,InfoData);
  2410.  
  2411.             /* Get information on file and filing system. */
  2412.  
  2413.         if(Examine(FileLock,FileInfo) && Info(FileLock,InfoData))
  2414.         {
  2415.             unsigned short mode = 0;
  2416.  
  2417.                 /* Try to get the name of the volume. */
  2418.  
  2419.             if(!NameFromLock(FileLock,Volume,sizeof(Volume)))
  2420.                 Volume[0] = 0;
  2421.             else
  2422.             {
  2423.                 WORD i;
  2424.  
  2425.                     /* Chop off everything after the colon. */
  2426.  
  2427.                 for(i = 0 ; i < sizeof(Volume) ; i++)
  2428.                 {
  2429.                     if(Volume[i] == ':')
  2430.                     {
  2431.                         Volume[i + 1] = 0;
  2432.  
  2433.                         break;
  2434.                     }
  2435.                 }
  2436.             }
  2437.  
  2438.             UnLock(FileLock);
  2439.  
  2440.                 /* Build the protection bits. */
  2441.  
  2442.             if(!(FileInfo->fib_Protection & FIBF_EXECUTE))
  2443.                 mode |= S_IEXECUTE;
  2444.  
  2445.             if(!(FileInfo->fib_Protection & FIBF_DELETE))
  2446.                 mode |= S_IDELETE;
  2447.  
  2448.             if(!(FileInfo->fib_Protection & FIBF_READ))
  2449.                 mode |= S_IREAD;
  2450.  
  2451.             if(!(FileInfo->fib_Protection & FIBF_WRITE))
  2452.                 mode |= S_IWRITE;
  2453.  
  2454.             if(!(FileInfo->fib_Protection & FIBF_ARCHIVE))
  2455.                 mode |= S_IARCHIVE;
  2456.  
  2457.             if(FileInfo->fib_Protection & FIBF_PURE)
  2458.                 mode |= S_IPURE;
  2459.  
  2460.             if(FileInfo->fib_Protection & FIBF_SCRIPT)
  2461.                 mode |= S_ISCRIPT;
  2462.  
  2463.                 /* Keep the comment. */
  2464.  
  2465.             CopyMem(FileInfo->fib_Comment,Comment,79);
  2466.             Comment[79] = 0;
  2467.  
  2468.                 /* Fix the time if necessary. */
  2469.  
  2470.             if(!TimerBase)
  2471.                 UpdateTime(NULL);
  2472.  
  2473.                 /* Fill in the data. */
  2474.  
  2475.             st->st_mode        = mode;
  2476.             st->st_ino        = FileInfo->fib_DiskKey;
  2477.             st->st_dev        = InfoData->id_DiskType;
  2478.             st->st_rdev        = Volume;
  2479.             st->st_nlink    = FileInfo->fib_DirEntryType == ST_SOFTLINK || FileInfo->fib_DirEntryType == ST_LINKDIR || FileInfo->fib_DirEntryType == ST_LINKFILE;
  2480.             st->st_uid        = FileInfo->fib_OwnerUID;
  2481.             st->st_gid        = FileInfo->fib_OwnerGID;
  2482.             st->st_size        = FileInfo->fib_Size;
  2483.             st->st_atime    = GMT_Offset + (FileInfo->fib_Date.ds_Days * 24 * 60 + FileInfo->fib_Date.ds_Minute) * 60 + (FileInfo->fib_Date.ds_Tick / TICKS_PER_SECOND);
  2484.             st->st_mtime    = st->st_atime;
  2485.             st->st_ctime    = st->st_atime;
  2486.             st->st_type        = FileInfo->fib_DirEntryType;
  2487.             st->st_comment    = Comment;
  2488.  
  2489.                 /* Success. */
  2490.  
  2491.             return(0);
  2492.         }
  2493.  
  2494.         UnLock(FileLock);
  2495.     }
  2496.  
  2497.         /* What else should I choose? */
  2498.  
  2499.     errno = _OSERR = EIO;
  2500.  
  2501.     return(-1);
  2502. }
  2503.